package org.helsoft.mojo.api;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.maven.artifact.Artifact;
//import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
import org.apache.maven.execution.DefaultMavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionRequestPopulationException;
import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.FileSet;
import org.apache.maven.model.Model;
import org.apache.maven.model.PatternSet;
import org.apache.maven.model.io.DefaultModelWriter;
import org.apache.maven.model.io.ModelWriter;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.StringUtils;

public abstract class AbstractBaseMojo extends AbstractLoggerMojo {

	/**
	 * The maven project.
	 * 
	 * @parameter expression="${project}"
	 * @required
	 */
	protected MavenProject project;
	/**
	 * The maven session.
	 *
	 * @parameter expression="${session}"
	 * @required
	 * @readonly
	 */
	private MavenSession session;
	/**
	 * The project helper
	 * 
	 * @component
	 * @readonly
	 */
	private MavenProjectHelper projectHelper;
	/**
	 * Location of the local repository.
	 * 
	 * @parameter expression="${localRepository}"
	 * @readonly
	 * @required
	 */
	protected org.apache.maven.artifact.repository.ArtifactRepository localRepository;
	/**
	 * The execution request populator
	 * 
	 * @component
	 * @readonly
	 */
	private org.apache.maven.execution.MavenExecutionRequestPopulator executionRequestPopulator;
//	/**
//	 * Used to look up Artifacts in the remote repository.
//	 * 
//	 * @component
//	 */
//	protected org.apache.maven.artifact.resolver.ArtifactResolver artifactResolver;
	/**
	 * Maven
	 * 
	 * @component
	 * @readonly
	 */
	protected org.apache.maven.Maven maven;
	/**
	 * List of Remote Repositories used by the resolver
	 * 
	 * @parameter expression="${project.remoteArtifactRepositories}"
	 * @readonly
	 * @required
	 */
	@SuppressWarnings("rawtypes")
	protected java.util.List remoteRepositories;

	public AbstractBaseMojo() {
		super();
	}

	/**
	 * @return the project
	 */
	public final MavenProject getProject() {
		return project;
	}

	/**
	 * @return the session
	 */
	public final MavenSession getSession() {
		return session;
	}

	/**
	 * @return the projectHelper
	 */
	public final MavenProjectHelper getProjectHelper() {
		return projectHelper;
	}

//	/**
//	 * @return the artifactResolver
//	 */
//	public final org.apache.maven.artifact.resolver.ArtifactResolver getArtifactResolver() {
//		return artifactResolver;
//	}

	/**
	 * @return the localRepository
	 */
	public final org.apache.maven.artifact.repository.ArtifactRepository getLocalRepository() {
		return localRepository;
	}

	/**
	 * @return the remoteRepositories
	 */
	@SuppressWarnings("rawtypes")
	public final java.util.List getRemoteRepositories() {
		return remoteRepositories;
	}

	/**
	 * A helper method to dump <code>Model</code> into a XML file.
	 * 
	 * @param model
	 *            The model
	 * @param destination
	 *            The destination
	 * @throws IOException
	 */
	protected void writeModel(Model model, File destination) throws IOException {
		ModelWriter writer = new DefaultModelWriter();
		writer.write(destination, null, model);
	}

//	/**
//	 * Attempts to resolve an {@link Artifact} to a {@link File}.
//	 * 
//	 * @param artifact
//	 *            to resolve
//	 * @return a {@link File} to the resolved artifact, never <code>null</code>.
//	 * @throws MojoExecutionException
//	 *             if the artifact could not be resolved.
//	 */
//	@SuppressWarnings("unchecked")
//	protected File resolveArtifactToFile(Artifact artifact)
//			throws MojoExecutionException {
//				ArtifactResolutionRequest request = new ArtifactResolutionRequest();
//				request.setRemoteRepositories(remoteRepositories);
//				request.setLocalRepository(localRepository);
//				request.setArtifact(artifact);
//				this.artifactResolver.resolve(request);
//				final File jar = artifact.getFile();
//				if (jar == null) {
//					throw new MojoExecutionException(
//							"Could not resolve artifact "
//									+ artifact.getId()
//									+ ". Please install it with \"mvn install:install-file ...\" or deploy it to a repository with \"mvn deploy:deploy-file ...\"");
//				}
//				return jar;
//			}

	/**
	 * Executes a maven request.
	 * 
	 * @param request
	 * @return
	 */
	protected MavenExecutionResult execute(MavenExecutionRequest request) {
	        return maven.execute(request);	
	   }

	/**
	 * Creates a new request a populate it with default values.
	 * 
	 * @return The request
	 */
	protected final MavenExecutionRequest createExecutionRequest() {
		MavenExecutionRequest request = new DefaultMavenExecutionRequest();
		try {
			executionRequestPopulator.populateDefaults(request);
		} catch (MavenExecutionRequestPopulationException e) {
			//FIXME Handle this exception in a better way
			e.printStackTrace();
		}
		return request;
	}

	/**
	 * @param dir
	 * @param patternSet
	 * @return
	 * @throws IOException
	 */
	protected final List<File> listFiles(File dir, PatternSet patternSet) throws IOException {
		List<File> list = new ArrayList<File>();
		String includes = "**/*";
		String excludes = FileUtils.getDefaultExcludesAsString();
		boolean isCaseSensitive = false;
		boolean includeBaseDir = false;
		boolean getFiles = true;
		boolean getDirectories = true;
		
		if (patternSet != null) {
			includes = StringUtils.join(patternSet.getIncludes()
					.iterator(), ",");
			if (patternSet.getExcludes().isEmpty()) {
				excludes += "," + StringUtils.join(patternSet.getExcludes()
						.iterator(), ",");
			}
		}
		
		for (Object obj : FileUtils.getFileAndDirectoryNames(dir, includes,
				excludes, includeBaseDir, isCaseSensitive, getFiles,
				getDirectories)) {
			list.add(new File(dir, "" + obj));
		}
		return list;
	}

	/**
	 * 
	 * @param fileSet
	 * @return
	 * @throws IOException
	 */
	protected final List<File> listFiles(FileSet fileSet) throws IOException {
		return listFiles(new File(getProject().getBasedir(), fileSet.getDirectory()), fileSet);
	}
	
	
}